<template>
  <div class="wrapper">
    <div v-for="(col, idx) in colCollect" :key="idx" :class="'col-' + (idx + 1)">
      <Item :goalHeight="GOAL_HEIGHT" :goalWidth="GOAL_WIDTH" :krHeight="KR_HEIGHT" :krWidth="KR_WIDTH" @openChild="openChild" @openKr="openKr" @addKr="addKr" @addGoalUnderKr="addGoalUnderKr" @editGoal="editGoal" v-for="item in col" :key="item.id" :goal="item"/>
    </div>
  </div>
</template>

<script>
import Item from './item'
import formUtil from "@/utils/formUtil";

export default {
  data() {
    return {
      GOAL_HEIGHT: 100, //目标高度
      GOAL_WIDTH: 260, //目标宽度
      KR_HEIGHT: 80, //kr高度
      KR_WIDTH: 220, //kr宽度
      GOAL_KR_TOP_OFFSET: 20, //目标与kr间距
      KR_KR_TOP_OFFSET: 10, //kr与kr间距
      GOAL_LEFT: 10, //目标左间距
      GOAL_KR_LEFT_OFFSET: 20, //目标与kr左间距
      GOAL_GOAL_TOP_OFFSET: 20, //目标与目标高度间距
      GOAL_DEFALUT_TOP: 10, //第一个目标坐标
      GOAL_DEFALUT_LEFT: 10, //第一个目标坐标
      colCollect: [],
      searchPost: {
        goalExecuteDepartmentId: '',
        goalPeriodYear: '',
        goalPeriodTime: '',
        krDataType: '',
        goalTag: '',
        limit: 999
      },
      goalListInit: '',
      goalBelongIds: []
    }
  },
  components: {
    Item
  },
  props: ["currentTime", "currentDeptId"],
  watch: {
    currentTime: {
      handler() {
        this.getGoalList();
      },
      deep: true
    },
    currentDeptId() {
      this.getGoalList();
    },
  },
  mounted() {},
  methods: {
    async getGoalList() {
      this.searchPost.goalPeriodYear = this.currentTime[0];
      this.searchPost.goalPeriodTime = this.currentTime[1];
      this.searchPost.goalExecuteDepartmentId = this.currentDeptId;
      let list = await this.$httpN.postB('lkr/goal/relationalGoalList', this.searchPost);
      let goalList = JSON.parse(JSON.stringify(list));
      this.goalBelongIds = goalList.map(x => {return x.goalBelongId})

      var ids = []
      let data = []
      goalList.reverse().forEach((goal, index) => {
        goal.show = false
        goal.belongId = goal.goalBelongId
        goal.top = 0
        goal.left = 0
        goal.topgoal = 0
        goal.height = 0
        goal.row = 1
        goal.goalChain = (index + 1).toString()
        goal.child = goal.krList
        goal.child.reverse().forEach(child => {
          if(!ids.includes(child.id)) ids.push(child.id)
          if(this.goalBelongIds.includes(child.id)) {
            child.hasChild = true;
            child.show = false;
          }
        })
        data.push(goal)
      })
      this.goalListInit = JSON.stringify(data);
      let list2 = data.filter(goal => {
        return goal.goalBelongId === '' || (!ids.includes(goal.goalBelongId))
      })
      this.colCollect = [];
      this.colCollect.push(list2)
      // this.openAllChild()
      this.computedGoalAndKrHeight();
    },
    openKr(goal) {
      goal.show = !goal.show
      if(!goal.show) this.closeKr(goal)
      this.computedGoalAndKrHeight();
    },
    closeKr(goal) {
      goal.child.forEach((kr, krIdx) => {
        kr.show = false
        this.closeChild(krIdx, goal, kr)
      })
    },
    openAllChild() {
      for(let i = 0; i < this.colCollect.length; i++){
        this.colCollect[i].forEach((goal, idx) => {
          if(goal.child.length > 0) this.openKr(goal)
          goal.child.forEach((child, childIdx) => {
            if(child.hasChild) this.openChild(childIdx, goal, child)
          })
        })
      }
      this.computedGoalAndKrHeight();
    },
    async updateData(type, goalId, krId) {
      this.getGoalList();
    },
    openChild(krIdx, goal, kr) {
      let goalIdx = this.colCollect[goal.row - 1].findIndex((item) => item.id === goal.id);
      let combineChain = `${goal.combineChain? goal.combineChain + '-': ''}${goal.goalChain}-${krIdx+1}`;
      let row = goal.row + 1;
      this.colCollect[goal.row - 1][goalIdx].child[krIdx].show = !this.colCollect[goal.row - 1][goalIdx].child[krIdx].show
      if(!this.colCollect[goal.row - 1][goalIdx].child[krIdx].show) return this.closeChild(krIdx, goal, kr)

      JSON.parse(this.goalListInit).forEach(element => {
        let newObj = {}
        if (element.goalBelongId === kr.id) {
          element.row = row
          element.left = 0
          element.combineChain = combineChain
          newObj = element
          this.colCollect[row-1] ? this.colCollect[row-1].push(newObj) : this.colCollect.push([newObj])
        }
      })
      this.computedGoalAndKrHeight();
    },
    closeChild(krIdx, goal, kr) {
      let goalIdx = this.colCollect[goal.row - 1].findIndex((item) => item.id === goal.id);
      let combineChain = `${goal.combineChain? goal.combineChain + '-': ''}${goal.goalChain}-${krIdx+1}`;
      
      //删除
      this.colCollect.forEach((col, idx) => {
        let newCol = col.filter((goal) => {
          if(goal.combineChain) {
            return goal.combineChain.indexOf(combineChain) !== 0
          }else {
            return true
          }
        })
        this.$set(this.colCollect, idx, newCol)
      })
      this.computedGoalAndKrHeight();
    },
    /**
     * 从左向右根据链路、goal高度、kr高度计算所有goal、kr的位置
     */
    computedChainPosition() {
      for(let i = 0; i < this.colCollect.length; i++){
        this.colCollect[i].forEach((goal, idx) => {
          //第二列及更后面的列数的goal的坐标是根据前一列所属的kr的高度来进行计算
          if(i !== 0 && goal.belongId) {
            //通过链路查找所属的kr
            let chainArr = goal.combineChain.split('-');
            //判断坐标由什么生成
            if(this.colCollect[i][idx - 1] && this.colCollect[i][idx - 1].belongId === goal.belongId) {
              //如果跟上一行的goal同属一个kr，则根据上一列来进行生成坐标
              goal.top = this.colCollect[i][idx - 1].top + this.colCollect[i][idx - 1].height + this.GOAL_GOAL_TOP_OFFSET;
              //记录前一行的goal高度用来划线使用
              goal.topgoal = this.colCollect[i][idx - 1].top;
            }else {
              //查找前一个kr并记录
              this.colCollect[i-1].forEach((element, index) => {
                if(element.goalChain === chainArr[chainArr.length - 2]) goal.top = this.colCollect[i-1][index].child[parseInt(chainArr[chainArr.length - 1]) - 1].top - (this.GOAL_HEIGHT - this.KR_HEIGHT) / 2
              })
            }
          }

          //第一列第二个及以后的goal计算位置 (实际应该不需要，只有一个总目标)
          if(i === 0 && idx !== 0) goal.top = this.colCollect[i][idx - 1].height + this.colCollect[i][idx - 1].top + this.GOAL_GOAL_TOP_OFFSET;
          
          goal.child.forEach((child, childIdx) => {
            //第一个kr 与 后面的kr坐标计算需要区分
            if(childIdx === 0) {
              //kr列数标记与goal相同
              child.row = goal.row;
              child.top = goal.top + this.GOAL_HEIGHT + this.GOAL_KR_TOP_OFFSET ;
              child.left = goal.left + this.GOAL_KR_LEFT_OFFSET;
            }else {
              child.row = goal.row;
              child.left = goal.left + this.GOAL_KR_LEFT_OFFSET;
              //如果kr高度是默认高度，则直接跟在上一个kr后面
              child.top = goal.child[childIdx - 1].top + this.KR_KR_TOP_OFFSET + goal.child[childIdx - 1].height;
            }
          })
        })
      }
    },
    /**
     * 从右向左计算kr高度、goal高度
     */
    computedGoalAndKrHeight() {
      this.resetAllGoalAndKrHeight();
      //遍历列数
      for(let i = this.colCollect.length - 1; i >= 0; i--){
        this.colCollect[i].forEach((goal, idx) => {
          // goal的高度计算：krChildHeightTotal 与 krHeightTotal比较 谁的值大用谁
          // krChildHeightTotal的计算方式：由kr自身高度、kr子高度进行比较获取，该计算方法比较复杂，如果当前够用就直接用，不行则根据实际情况进行调整
          // krHeightTotal的计算方式：kr个数相乘

          //第一种计算方式
          let krChildHeightTotal = 0;
          if(goal.show) {
            goal.child.forEach((child, childIdx) => {
              //由于之前重置过，设置默认高度
              if(child.height === 0) child.height = this.KR_HEIGHT;
              //如果kr高度大于默认高度, 则高度是以kr高度为准
              if(child.height > this.KR_HEIGHT) krChildHeightTotal += child.height + this.GOAL_GOAL_TOP_OFFSET;
              //如果第一个子kr是原始高度，则直接加上kr高度
              if(childIdx === 0 && child.height === this.KR_HEIGHT) krChildHeightTotal += child.height;
              //除了第一个以外，如果上一个是原始高度当前也是原始高度 则相加
              if(childIdx >= 1 && child.height === this.KR_HEIGHT && goal.child[childIdx -1].height === this.KR_HEIGHT) {
                krChildHeightTotal += child.height
              }
              if(childIdx === (goal.child.length - 1) && childIdx !== 0)  krChildHeightTotal += this.GOAL_HEIGHT
            })
          }

          //第二种计算方式
          let krHeightTotal = 0;
          if(goal.show) krHeightTotal = (this.KR_HEIGHT + this.GOAL_KR_TOP_OFFSET)*goal.child.length;

          //获取目标最终高度，当前都没有加偏移量，因为随着列数增长，可以稍微少增加点高度，也不会阻挡其他节点显示，如果实际情况需要则加上
          goal.height = (krHeightTotal >= krChildHeightTotal ? krHeightTotal: krChildHeightTotal) + this.GOAL_HEIGHT;
          
          //给所属的kr加上高度，如果多个goal属于同一个kr，可叠加高度
          if(goal.belongId && i !== 0) {
            let chainArr = goal.combineChain.split('-');
            let goalChain = chainArr[chainArr.length - 2];
            this.colCollect[i-1].forEach((element, index) => {
              //加上偏移量，连续两个关键结果有子目标，目标会重叠
              if(element.goalChain === goalChain) this.colCollect[i-1][index].child[parseInt(chainArr[chainArr.length - 1]) - 1].height += goal.height + this.GOAL_GOAL_TOP_OFFSET;
            })
          }
        })
      }
      this.computedChainPosition()
    },
    /**
     * 重置所有高度：当节点变化的时候，高度会发生变化，先重置后重新计算
     */
    resetAllGoalAndKrHeight() {
      this.colCollect.forEach((col) => {
        col.forEach((goal) => {
          goal.height = 0;
          goal.child.forEach((child) => {
            child.height = 0;
          })
        })
      })
    },
    addKr(krId, goalId, goalName) {
      this.$emit("addKr", krId, goalId, goalName)
    },
    addGoalUnderKr(krId, krName) {
      this.$emit("addGoalUnderKr", krId, krName)
    },
    editGoal(goalId) {
      this.$emit("editGoal", goalId)
    }
  }
}
</script>

<style lang="scss" scoped>
.wrapper::-webkit-scrollbar {/*滚动条整体样式*/
  width: 4px;     /*高宽分别对应横竖滚动条的尺寸*/
  height: 4px;
  scrollbar-arrow-color:red;
}
.wrapper::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
  border-radius: 5px;
  -webkit-box-shadow: inset 0 0 5px #DEDEDE;
  background: rgba(0,0,0,0.2);
  scrollbar-arrow-color:red;
}
.wrapper::-webkit-scrollbar-track {/*滚动条里面轨道*/
  -webkit-box-shadow: inset 0 0 5px #F5F5F5;
  border-radius: 0;
  background: rgba(0,0,0,0.1);
}
.wrapper{
  width:100%;
  height: 100%;
  overflow: auto;
  background: #F6F6F6;
  display: flex;
  div[class^='col']{
    height: 100%;
    width: 352px;
    min-width: 352px;
    position: relative;
  }
}
</style>